package org.feng.fxfront.sys;


import org.feng.api.sys.annotations.PageNodeKey;
import org.feng.fxfront.util.StringUtil;

import java.lang.reflect.InvocationTargetException;
import java.util.*;

/**
 * PageNodeRender工厂
 *
 * @author feng
 */
public class PageNodeRenderFactory {

    private static final Map<String, PageNodeRender> PAGE_NODE_RENDER_MAP = new HashMap<>(8);

    private static final Set<PageNodeDefine> PAGE_NODE_DEFINES = new TreeSet<>(Comparator.comparingInt(PageNodeDefine::getOrder)
            .thenComparing(PageNodeDefine::getPageKey));

    private static final Map<String, String> PAGE_NAME_MAP = new LinkedHashMap<>();
    private static final Map<String, String> RESERVE_PAGE_NAME_MAP = new LinkedHashMap<>();

    public static PageNodeRender newInstance(String pageKey) {
        return PAGE_NODE_RENDER_MAP.get(pageKey);
    }

    public static Map<String, String> getPageNameMap() {
        return PAGE_NAME_MAP;
    }

    public static String getPageKeyByName(String pageName) {
        return RESERVE_PAGE_NAME_MAP.get(pageName);
    }


    public static void registerNodeRender(Class<? extends PageNodeRender> renderClass) {
        try {
            // 处理PageNodeRender#getPageKey()
            PageNodeRender pageNodeRender = renderClass.getDeclaredConstructor().newInstance();
            String pageKey = pageNodeRender.getPageKey();
            if (StringUtil.isNotEmpty(pageKey)) {
                PAGE_NODE_RENDER_MAP.put(pageKey, pageNodeRender);

                PageNodeDefine pageNodeDefine = new PageNodeDefine();
                pageNodeDefine.setPageKey(pageKey);
                pageNodeDefine.setPageName(pageNodeRender.getPageName());
                pageNodeDefine.setOrder(pageNodeRender.order());
                PAGE_NODE_DEFINES.add(pageNodeDefine);
                return;
            }

            // 处理PageNodeKey注解
            if (renderClass.isAnnotationPresent(PageNodeKey.class)) {
                PageNodeKey pageNodeKey = renderClass.getAnnotation(PageNodeKey.class);
                pageKey = pageNodeKey.value();
                if (StringUtil.isNotEmpty(pageKey)) {
                    PAGE_NODE_RENDER_MAP.put(pageKey, pageNodeRender);

                    PageNodeDefine pageNodeDefine = new PageNodeDefine();
                    pageNodeDefine.setPageKey(pageKey);
                    pageNodeDefine.setPageName(pageNodeKey.pageName());
                    pageNodeDefine.setOrder(pageNodeKey.order());
                    PAGE_NODE_DEFINES.add(pageNodeDefine);
                    return;
                }
            }

            throw new IllegalArgumentException(renderClass.getName() + "定义错误，请检查");
        } catch (NoSuchMethodException | InvocationTargetException | InstantiationException |
                 IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }


    public static void fillPageNameMap() {
        PAGE_NODE_DEFINES.forEach(pageNodeDefine -> {
            PAGE_NAME_MAP.put(pageNodeDefine.getPageKey(), pageNodeDefine.getPageName());
            RESERVE_PAGE_NAME_MAP.put(pageNodeDefine.getPageName(), pageNodeDefine.getPageKey());
        });
    }
}
